package com.tca.common.learning.elasticsearch;

import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Lists;
import com.tca.common.core.utils.ValidateUtils;
import com.tca.common.learning.elasticsearch.bean.User;
import lombok.extern.slf4j.Slf4j;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.sort.SortOrder;

import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author zhoua
 * @date 2022/1/13 19:53
 */
@Slf4j
public class DocComplexQuery {

    /**
     * 核心客户端
     */
    private static RestHighLevelClient client = EsClientFactory.getClient();

    public static void main(String[] args) throws IOException {
        // 1.查询所有
        List<User> list = queryAll("user", User.class);
        log.info("查询结果: {}", list);

        // 2.单条件查询
        list = queryCondition("user", User.class, "age", 30);
        log.info("查询结果: {}", list);

        // 3.分页查询
        list = queryPage("user", User.class, 1, 2);
        log.info("查询结果: {}", list);

        // 4.复合条件查询
        Map<String, Object> conditions = new HashMap<>(4);
        conditions.put("age", 30);
        conditions.put("sex" , "女");
        list = queryMultiCondition("user", User.class, conditions);
        log.info("查询结果: {}", list);




        client.close();

    }



    /**
     * 复合条件查询
     * @param index
     * @param clazz
     * @param conditions
     * @param <T>
     * @return
     */
    private static <T> List<T> queryMultiCondition(String index, Class<T> clazz, Map<String, Object> conditions) throws IOException {
        if (ValidateUtils.isEmpty(conditions)) {
            return queryAll(index, clazz);
        }
        List<T> list = Lists.newArrayList();
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
        conditions.entrySet().forEach(entry -> {
            boolQueryBuilder.must(QueryBuilders.matchQuery(entry.getKey(), entry.getValue()));
        });
        searchSourceBuilder.query(boolQueryBuilder);
        SearchRequest request = new SearchRequest()
                .indices(index)
                .source(searchSourceBuilder);
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);
        SearchHits hits = response.getHits();
        hits.forEach(hit -> {
            String json = hit.getSourceAsString();
            list.add(JSONObject.parseObject(json, clazz));

        });
        return list;
    }

    /**
     * 分页查询
     * @param index
     * @param clazz
     * @param <T>
     * @param page
     * @param size
     * @return
     */
    private static <T> List<T> queryPage(String index, Class<T> clazz, int page, int size) throws IOException {
        if (page < 1) {
            page = 1;
        }

        String[] include = new String[]{"name", "age"};
        String[] exclude = new String[]{};
        List<T> list = Lists.newArrayList();
        SearchRequest request = new SearchRequest()
                .indices(index)
                .source(new SearchSourceBuilder()
                        .query(QueryBuilders.matchAllQuery())
                                        // 分页
                                        .from((page - 1) * size)
                                        .size(size)
                                        // 排序
                                        .sort("age", SortOrder.DESC)
                                        .fetchSource(include, exclude));
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);
        SearchHits hits = response.getHits();
        hits.forEach(hit -> {
            String json = hit.getSourceAsString();
            list.add(JSONObject.parseObject(json, clazz));

        });
        return list;
    }


    /**
     * 单条件查询
     * @param clazz
     * @param <T>
     * @return
     */
    private static <T> List<T> queryCondition(String index, Class<T> clazz, String key, Object value) throws IOException {
        if (ValidateUtils.isEmpty(key)) {
            return queryAll(index, clazz);
        }
        List<T> list = Lists.newArrayList();
        SearchRequest request = new SearchRequest()
                .indices(index)
                .source(new SearchSourceBuilder().query(
                    QueryBuilders.termQuery(key, value)
                ));
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);
        SearchHits hits = response.getHits();
        hits.forEach(hit -> {
            String json = hit.getSourceAsString();
            list.add(JSONObject.parseObject(json, clazz));

        });
        return list;
    }


    /**
     * 查询所有
     * @param index
     * @param clazz
     * @param <T>
     * @return
     * @throws IOException
     */
    private static <T> List<T> queryAll(String index, Class<T> clazz) throws IOException {
        List<T> list = Lists.newArrayList();
        SearchRequest request = new SearchRequest()
                .indices(index)
                .source(new SearchSourceBuilder().query(QueryBuilders.matchAllQuery()));
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);
        SearchHits hits = response.getHits();
        hits.forEach(hit -> {
            String json = hit.getSourceAsString();
            list.add(JSONObject.parseObject(json, clazz));

        });
        return list;
    }
}
